Mobile terminal: flash fix, key bar, scroll momentum - #1
Merged
Conversation
Rows-only overflow now renders one-to-one with the bottom rows briefly clipped instead of scaling the whole surface down: the uniform factor pinched both axes for the settle window, a visible lurch on every keyboard open. Scaling remains for column overflow, where clipping would amputate lines.
Arrows follow DECCKM (CSI for a shell, SS3 for vim and friends), Ctrl-arrows are the modified CSI form either way, and a sticky Ctrl folds the next typed byte onto its control code. Pure functions ahead of the bar that will press them.
Esc, tab, a sticky ctrl and the four arrows, floated over the terminal's bottom edge on coarse-pointer devices only. Arrows follow DECCKM through a new emulator seam method, ctrl folds the next keystroke on the input path, and presses ride pointerdown with the default prevented so the soft keyboard stays open. The inset reserves the bar's room, so it covers no rows.
VoiceOver's and TalkBack's double-tap synthesise a click and dispatch no pointer event at all, and so does Enter on a hybrid device's keyboard — so a bar wired to pointerdown alone offered a named, aria-pressed control that answered nothing, on exactly the devices it exists for. Each chip gains an onClick guarded on detail === 0, which is true only of a synthesised click, so a finger's own follow-up click still cannot send the key twice. Pointerdown and its prevented default are untouched: the soft keyboard stays open as before. Also pins the latched Ctrl's other half — the arming is spent even on a keystroke that cannot fold. Nothing distinguished that from moving the spend inside the fold check, which would latch Ctrl for good after a digit.
Drags scrolled line-for-line and stopped dead at the lift, which reads as rigid to a thumb calibrated by every other scrolling surface on a phone. A release velocity now decays at UIKit's 0.998-per-millisecond rate, emitting whole lines with the fraction carried, and dies at the next touch, a pinch, or unmount.
The release velocity was measured from touchdown, because the anchor sample stayed in the window for the whole of any flick shorter than six moves. Touching the glass to stop a glide, hesitating, then flicking is the commonest gesture there is, and the hesitation was being averaged into the answer: a 125 lines/s flick after a 200ms pause read as 17 and glided an eighth as far. Samples older than 100ms are now dropped, two always kept so a short flick still reads.
touchcancel shared the lift handler, and a drag the system takes away — the notification shade, an alert, a call — leaves samples that read as a flick: fast, recent, promptly followed by an event. The scrollback would coast on with nothing on the glass. It gets its own handler now, one that clears the gesture and reaches startGlide by no path. The latched Ctrl was spent through state alone, so the ref the input path reads stayed armed until React flushed. Two onData deliveries in one task both folded, and one press of ctrl produced two control codes. The ref is now cleared by hand beside both setCtrlArmed(false) sites. applicationCursorKeys reached into a possibly-disposed terminal without the guard its three neighbours carry — harmless in the xterm shipped today, which is a fact about xterm's internals rather than about this seam. Two comments that named "the three below" and "the last three" had outlived the member sets they counted, and now say what is there. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three mobile-terminal improvements, following up the visual-viewport / pty-sizing branch.
Keyboard-open flash
relayoutscaled the whole surface by a uniform factor whenever the pty stopped fitting in either axis, so a keyboard taking half the pane's height pinched the width too for the ~150ms settle window. The surface now renders one-to-one whenever every column fits — rows-only overflow clips briefly behind the keyboard instead, and the width never moves. Scaling remains for column overflow, where clipping would amputate lines.On-screen key bar (touch devices only)
ctrlesctab← ↓ ↑ →chips floated over the terminal's bottom edge, in the chip style of the existing control strip.Emulator.applicationCursorKeys()seam method: CSI at a shell, SS3 once vim or another full-screen program has asked — same as a hardware keyboard through xterm.ctrl+csends 0x03.detail === 0click guard.Scroll momentum
Flicks glide: release velocity is read from the last 100ms of drag samples (so touch-pause-flick reads the flick, not the pause) and decays at UIKit's 0.998-per-millisecond rate, emitting whole lines with the fraction carried. A finger back on the glass, a pinch,
touchcancel, or unmount kills it.Review trail
Per-task reviews plus a whole-branch pass; three fix rounds landed AT activation, the Ctrl-spend test (mutation-proven), and the flick-window trim. Suite: 599 web tests + real-build Tailwind-scanner guard +
tscclean.Before release: real-device pass — clip direction on keyboard open, bar fit on a 320px phone, VoiceOver/TalkBack double-tap, glide feel.
🤖 Generated with Claude Code